package indi.lqzhi.tcpserver;


import cn.hutool.core.util.StrUtil;
import indi.lqzhi.tcpserver.base.AbstractServer;
import indi.lqzhi.tcpserver.handler.BusChannelHandler;
import indi.lqzhi.tcpserver.manager.BusManager;
import indi.lqzhi.tcpserver.message.BusMessage;
import indi.lqzhi.tcpserver.pipeline.BusPipeline;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import lombok.extern.slf4j.Slf4j;
import lombok.var;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * @Author: LQZhi
 * @ClassName: GeneralServer
 * @Date: 2021-09-29 22-33
 * @Description: 通用总线服务器
 * @Version: V1.0
 */
@Slf4j
public class GeneralBusServer extends AbstractServer {

    private Executor asyncBusExecutor;

    /**
     * 绑定的IP和端口号
     */
    private SocketAddress socketAddress;

    /**
     * 通用的处理器
     */
    private  ChannelHandler[] channelHandlers;

    /**
     * 总线通道
     */
    private BusPipeline pipeline;

    /**
     * 总线管理器
     */
    private BusManager manager;

    /**
     * 默认处理器
     */
    private final ChannelHandler defaultChannelHandler;

    /**
     * 发送处理器
     */
    private final Consumer<BusMessage> defaultWriteHandler = busMessage -> {
        if (busMessage == null){
            return;
        }
        //处理
        var id = busMessage.getId();
        var bytes = busMessage.getObject();
        if (StrUtil.isBlank(id)){
            //发送全部
            synchronized (GeneralBusServer.this){
                //同步代码块
                var clients = manager.getAllClient();
                for (var client: clients) {
                    //发送
                    ByteBuf buffer = client.alloc().buffer(bytes.length);//申请ByteBuf
                    buffer.writeBytes(bytes);//写入数据
                    client.writeAndFlush(buffer);//写入并且发送
                }
            }
            return;
        }

        //根据key发送
        synchronized (GeneralBusServer.this){
            var client = manager.getClient(id);
            client.ifPresent(v -> {
                //处理
                ByteBuf buffer = v.alloc().buffer(bytes.length);//申请ByteBuf
                buffer.writeBytes(bytes);//写入数据
                v.writeAndFlush(buffer);//写入并且发送
            });
        }
    };

    /**
     * 构造函数
     * @param port 端口号
     */
    public GeneralBusServer(int port){
        this(new InetSocketAddress(port),null,null);
    }

    /**
     * 构造函数
     * @param socketAddress 绑定的host和端口号
     */
    public GeneralBusServer(SocketAddress socketAddress){
        this(socketAddress,null,null);
    }

    /**
     * 构造函数
     * @param socketAddress 绑定的host和端口号
     * @param channelHandlers 处理器
     */
    public GeneralBusServer(SocketAddress socketAddress,ChannelHandler[] channelHandlers){
        this(socketAddress,channelHandlers,null);
    }

    /**
     * 构造函数
     * @param socketAddress 绑定的host和端口号
     * @param asyncBusExecutor 线程池
     */
    public GeneralBusServer(SocketAddress socketAddress,Executor asyncBusExecutor){
        this(socketAddress,null,asyncBusExecutor);
    }

    /**
     * 通过构造器
     * @param socketAddress 地址
     * @param channelHandlers 处理器
     */
    public GeneralBusServer(SocketAddress socketAddress,ChannelHandler[] channelHandlers,Executor asyncBusExecutor) {
        this.socketAddress = Objects.requireNonNull(socketAddress);
        this.channelHandlers = channelHandlers;
        this.asyncBusExecutor= asyncBusExecutor;
        pipeline = new BusPipeline(asyncBusExecutor);
        pipeline.registerWriteMessageHandlers(defaultWriteHandler);//注册写消息处理器
        manager = new BusManager();
        defaultChannelHandler = new BusChannelHandler(manager,pipeline);
    }

    /**
     * 供给客户端连接后进行处理的管道
     *
     * @return ChannelHandler 管道处理器，处理读，写事件
     */
    @Override
    protected ChannelHandler[] configChannelHandler() {
        return channelHandlers != null ? channelHandlers : new ChannelHandler[]{defaultChannelHandler};
    }

    /**
     * 供给服务器引导者绑定的服务器地址
     *
     * @return socketAddress 服务器绑定的主机和端口地址
     */
    @Override
    protected SocketAddress configServerAddress() {
        return socketAddress;
    }

    @Override
    public void start() {
        super.start();
        pipeline.start();
    }

    @Override
    public void stop() {
        super.stop();
        pipeline.destory();
    }

    /**
     * 获取SokcetAddress
     * @return 服务器绑定的Socket地址
     */
    public SocketAddress getSocketAddress() {
        return socketAddress;
    }


    public void setChannelHandlers(ChannelHandler[] channelHandlers) {
        this.channelHandlers = Objects.requireNonNull(channelHandlers);
    }

    public void setSocketAddress( SocketAddress socketAddress) {
        this.socketAddress = Objects.requireNonNull(socketAddress);
    }

    public BusPipeline getPipeline() {
        return pipeline;
    }

    public BusManager getManager() {
        return manager;
    }

}
